package com.able.concurrency.t5;

import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * @author abel.he
 * @data 2018/10/29 13:42
 * @describe
 * 分支合并线程池
 */
public class Test7_ForkJoinPoll {

    static final Integer[] numbers = new Integer[10000000];
    static final int MAX_VALUE = 5000;
    static final Random random = new Random();

    static {
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = random.nextInt(1000);
        }
    }

    static class AddTask extends RecursiveTask<Long> {

        int begin, end;

        public AddTask(int begin, int end) {
            this.begin = begin;
            this.end = end;
        }

        @Override
        protected Long compute() {
            Long result = 0L;
            if ((end - begin) < MAX_VALUE) {
                for (int i = begin; i < end ; i++) {
                    result += numbers[i];
                }
                return result;
            }
            int middle = begin + (end-begin)/2;
            AddTask task1 = new AddTask(begin, middle);
            AddTask task2 = new AddTask(middle, end);
            // 就是用于开启新的任务的。 就是分支工作的。 就是开启一个新的线程任务。
            task1.fork();
            task2.fork();

            // join - 合并。将任务的结果获取。 这是一个阻塞方法。一定会得到结果数据。
            return task1.join() + task2.join();
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        long result = 0L;
        long beginTime = System.currentTimeMillis();
        for (int i = 0; i < numbers.length; i++) {
            result += numbers[i];
        }
        System.out.println("执行时间：" + (System.currentTimeMillis()-beginTime) + "ms");
        System.out.println(result);

        ForkJoinPool forkJoinPool = new ForkJoinPool();
        AddTask task = new AddTask(0, numbers.length);
        ForkJoinTask<Long> future = forkJoinPool.submit(task);
        System.out.println("执行时间：" + (System.currentTimeMillis()-beginTime) + "ms");
        System.out.println(future.get());


    }

}
